package com.ljf.task.domain.validator;

import com.ljf.authority.domain.repository.AuthorityBaseMenuTabulationRepository;
import com.ljf.authority.dto.query.AuthorityBaseMenuTabulationQuery;
import com.ljf.common.domain.validator.BasisValidator;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.EnumUtil;
import com.ljf.task.domain.repository.TaskDatTaskDetailRepository;
import com.ljf.task.domain.repository.TaskDatTaskTabulationRepository;
import com.ljf.task.dto.command.*;
import com.ljf.task.dto.query.TaskDatTaskTabulationQuery;
import com.ljf.task.enums.TaskDatTaskDetailDetailStatusEnum;
import com.ljf.task.enums.TaskDatTaskTabulationTaskStatusEnum;
import com.ljf.task.enums.TaskDatTaskTabulationTaskTypeEnum;
import com.ljf.task.model.TaskDatTaskTabulation;
import com.ljf.task.vo.TaskDatTaskDetailVO;
import com.ljf.task.vo.TaskDatTaskTabulationVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

/**
 * 任务列表  业务校验
 *
 * @author LJF
 * @since 2024-12-25
 */
@Component
@AllArgsConstructor
public class TaskDatTaskTabulationValidator extends BasisValidator<TaskDatTaskTabulationQuery, TaskDatTaskTabulationCommand, TaskDatTaskTabulationVO, TaskDatTaskTabulation, TaskDatTaskTabulationRepository> {

    private final TaskDatTaskDetailRepository detailRepository;
    private final AuthorityBaseMenuTabulationRepository authorityBaseMenuTabulationRepository;

    @Override
    public void checkAdd(TaskDatTaskTabulationCommand command) throws ServiceException {
        super.checkAdd(command);
        int menuCount = authorityBaseMenuTabulationRepository.count(
                AuthorityBaseMenuTabulationQuery.builder().code(command.getMenuCode()).build()
        );
        if (menuCount == 0) {
            throw new ServiceException("任务新增校验异常: 菜单不存在");
        }
        if (!EnumUtil.checkCode(command.getTaskType(), TaskDatTaskTabulationTaskTypeEnum.values())) {
            throw new ServiceException("任务新增校验异常: 任务类型不存在");
        }
    }

    @Override
    public void checkDeleteBatch(List<Long> ids) throws ServiceException {
        super.checkDeleteBatch(ids);
        List<TaskDatTaskTabulationVO> modelList = repository.selectListByIds(ids);
        if (ids.size() != modelList.size()) {
            throw new ServiceException("任务删除校验异常: 数据不存在, 请刷新后重试");
        }
        boolean notDesignedStatus = modelList.stream().anyMatch(
                one -> !Objects.equals(one.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.TO_BE_DESIGNED.getCode())
        );
        if (notDesignedStatus) {
            throw new ServiceException(String.format("任务删除校验异常: 非【%s】状态任务, 不允许删除", TaskDatTaskTabulationTaskStatusEnum.TO_BE_DESIGNED.getName()));
        }
    }

    @Override
    public void checkEdit(TaskDatTaskTabulationCommand command) throws ServiceException {
        super.checkEdit(command);
        TaskDatTaskTabulationVO model = repository.selectById(command.getId());
        if (model == null) {
            throw new ServiceException("任务修改校验异常: 数据不存在, 请刷新后重试");
        }
        if (!Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.TO_BE_DESIGNED.getCode()) && !Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.DESIGN.getCode())) {
            throw new ServiceException(String.format("任务修改校验异常: 非【%s】或者【%s】状态任务, 不允许删除", TaskDatTaskTabulationTaskStatusEnum.TO_BE_DESIGNED.getName(), TaskDatTaskTabulationTaskStatusEnum.DESIGN.getName()));
        }
        int menuCount = authorityBaseMenuTabulationRepository.count(
                AuthorityBaseMenuTabulationQuery.builder().code(command.getMenuCode()).build()
        );
        if (menuCount == 0) {
            throw new ServiceException("任务新增校验异常: 菜单不存在");
        }
    }

    /**
     * 更新任务状态 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditTaskStatus(TaskDatTaskTabulationTaskStatusCommand command) throws ServiceException {
        super.checkNullId(command.getId());
        if (!EnumUtil.checkCode(command.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.values())) {
            throw new ServiceException("更新任务状态校验异常: 参数异常");
        }
        TaskDatTaskTabulationVO model = repository.selectById(command.getId());
        if (model == null) {
            throw new ServiceException("更新任务状态校验异常: 数据不存在, 请刷新后重试");
        }
        TaskDatTaskTabulationTaskStatusEnum taskStatusEnum = EnumUtil.getEnumByCode(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.values());
        if (taskStatusEnum == null) {
            throw new ServiceException("更新任务状态校验异常: 数据异常");
        }
        if (Objects.equals(command.getTaskStatus(), model.getTaskStatus())) {
            throw new ServiceException("更新任务状态校验异常: 状态一致, 无需更新");
        }
        else if (command.getTaskStatus() > model.getTaskStatus()) {
            int taskStatus = model.getTaskStatus();
            do {
                taskStatus++;
                if (Objects.equals(taskStatus, TaskDatTaskTabulationTaskStatusEnum.DESIGN.getCode())) {
                    throw new ServiceException(String.format("更新任务状态校验异常: 无法从【%s】更新到【%s】, 需要通过【设计】处理", taskStatusEnum.getName(), TaskDatTaskTabulationTaskStatusEnum.DESIGN.getName()));
                }
                if (Objects.equals(taskStatus, TaskDatTaskTabulationTaskStatusEnum.TO_BE_DEVELOPED.getCode())) {
                    throw new ServiceException(String.format("更新任务状态校验异常: 无法从【%s】更新到【%s】, 需要通过【设计】处理", taskStatusEnum.getName(), TaskDatTaskTabulationTaskStatusEnum.TO_BE_DEVELOPED.getName()));
                }
                if (Objects.equals(taskStatus, TaskDatTaskTabulationTaskStatusEnum.DEVELOPING.getCode())) {
                    throw new ServiceException(String.format("更新任务状态校验异常: 无法从【%s】更新到【%s】, 需要通过【开发】处理", taskStatusEnum.getName(), TaskDatTaskTabulationTaskStatusEnum.DEVELOPING.getName()));
                }
                if (Objects.equals(taskStatus, TaskDatTaskTabulationTaskStatusEnum.JOINT_DEBUGGING_IN_PROGRESS.getCode())) {
                    throw new ServiceException(String.format("更新任务状态校验异常: 无法从【%s】更新到【%s】, 需要通过【开发】处理", taskStatusEnum.getName(), TaskDatTaskTabulationTaskStatusEnum.JOINT_DEBUGGING_IN_PROGRESS.getName()));
                }
            }
            while (command.getTaskStatus() >= taskStatus);
        }
    }

    /**
     * 获取提交信息文本 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryCommitMessageById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 根据ID查询任务设计信息 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryDesignMessageById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 更新任务明细草稿 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditDetailDraft(TaskDatTaskTabulationDesignCommand command) throws ServiceException {
        this.checkEditDetail("更新任务明细草稿校验异常", command);
    }

    /**
     * 更新任务明细终稿 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditDetailFinalDraft(TaskDatTaskTabulationDesignCommand command) throws ServiceException {
        this.checkEditDetail("更新任务明细终稿校验异常", command);
    }

    /**
     * 根据ID查询任务开发信息 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryDevelopMessageById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 更新任务明细开发状态 业务校验
     *
     * @param command
     * @throws ServiceException
     */
    public void checkEditDetailDevelopStatus(TaskDatTaskDetailStatusCommand command) throws ServiceException {
        if (!EnumUtil.checkCode(command.getDetailStatus(), TaskDatTaskDetailDetailStatusEnum.values())) {
            throw new ServiceException("更新任务明细开发状态校验异常: 参数异常");
        }
        super.checkNullId(command.getId());
        TaskDatTaskDetailVO detail = detailRepository.selectById(command.getId());
        if (detail == null) {
            throw new ServiceException("更新任务明细开发状态校验异常: 数据不存在, 请刷新后重试");
        }
        TaskDatTaskTabulationVO model = repository.selectOne(TaskDatTaskTabulationQuery.builder().code(detail.getCode()).build());
        if (!Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.TO_BE_DEVELOPED.getCode()) && !Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.DEVELOPING.getCode()) && !Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.JOINT_DEBUGGING_IN_PROGRESS.getCode())) {
            throw new ServiceException(String.format("更新任务明细开发状态校验异常: 非【%s】、【%s】或者【%s】状态任务, 不允许处理", TaskDatTaskTabulationTaskStatusEnum.TO_BE_DEVELOPED.getName(), TaskDatTaskTabulationTaskStatusEnum.DEVELOPING.getName(), TaskDatTaskTabulationTaskStatusEnum.JOINT_DEBUGGING_IN_PROGRESS.getName()));
        }
    }

    /**
     * 根据ID查询任务开发提交内容 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryDetailSubmitMessageById(Long id) throws ServiceException {
        super.checkNullId(id);
        TaskDatTaskDetailVO detail = detailRepository.selectById(id);
        if (detail == null) {
            throw new ServiceException("根据ID查询任务开发提交内容校验异常: 数据不存在, 请刷新后重试");
        }
        if (!Objects.equals(TaskDatTaskDetailDetailStatusEnum.PROCESSING.getCode(), detail.getDetailStatus())) {
            throw new ServiceException(String.format("根据ID查询任务开发提交内容校验异常: 仅允许【%s】状态复制提交信息", TaskDatTaskDetailDetailStatusEnum.PROCESSING.getName()));
        }
    }

    /**
     * 根据ID查询任务状态 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryTaskStatusById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 根据ID查询任务操作历史 业务校验
     *
     * @param id
     * @throws ServiceException
     */
    public void checkQueryOperateHistoryById(Long id) throws ServiceException {
        super.checkIdExist(id);
    }

    /**
     * 检查编辑明细
     *
     * @param msg
     * @param command
     * @throws ServiceException
     */
    private void checkEditDetail(String msg, TaskDatTaskTabulationDesignCommand command) throws ServiceException {
        super.checkNullId(command.getId());
        TaskDatTaskTabulationVO model = repository.selectById(command.getId());
        if (model == null) {
            throw new ServiceException(msg + ": 数据不存在, 请刷新后重试");
        }
        if (!Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.TO_BE_DESIGNED.getCode()) && !Objects.equals(model.getTaskStatus(), TaskDatTaskTabulationTaskStatusEnum.DESIGN.getCode())) {
            throw new ServiceException(msg + String.format(": 非【%s】或者【%s】状态任务, 不允许处理", TaskDatTaskTabulationTaskStatusEnum.TO_BE_DESIGNED.getName(), TaskDatTaskTabulationTaskStatusEnum.DESIGN.getName()));
        }
        TaskDatTaskTabulationTaskTypeEnum taskTypeEnum = EnumUtil.getEnumByCode(model.getTaskType(), TaskDatTaskTabulationTaskTypeEnum.values());
        if (taskTypeEnum == null) {
            throw new ServiceException(msg + ": 数据类型异常");
        }
        List<Long> detailIds = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(command.getDatabaseProcessingList())) {
            if (Boolean.FALSE.equals(taskTypeEnum.getDatabaseProcessing())) {
                throw new ServiceException(msg + ": 任务状态异常, 请刷新后重试");
            }
            command.getDatabaseProcessingList().sort(Comparator.comparing(TaskDatTaskDetailCommand::getSort));
            int index = 1;
            for (TaskDatTaskDetailCommand detailCommand : command.getDatabaseProcessingList()) {
                if (detailCommand.getSort() == null || detailCommand.getSort() != index) {
                    throw new ServiceException(msg + ": 数据库处理明细排序异常");
                }
                index++;
                if (detailCommand.getId() != null) {
                    detailIds.add(detailCommand.getId());
                }
            }
        }
        if (CollectionUtil.isNotEmpty(command.getFrontEndDevelopmentList())) {
            if (Boolean.FALSE.equals(taskTypeEnum.getFrontEndDevelopment())) {
                throw new ServiceException(msg + ": 任务状态异常, 请刷新后重试");
            }
            command.getFrontEndDevelopmentList().sort(Comparator.comparing(TaskDatTaskDetailCommand::getSort));
            int index = 1;
            for (TaskDatTaskDetailCommand detailCommand : command.getFrontEndDevelopmentList()) {
                if (detailCommand.getSort() == null || detailCommand.getSort() != index) {
                    throw new ServiceException(msg + ": 前端开发明细排序异常");
                }
                index++;
                if (detailCommand.getId() != null) {
                    detailIds.add(detailCommand.getId());
                }
            }
        }
        if (CollectionUtil.isNotEmpty(command.getBackendDevelopmentList())) {
            if (Boolean.FALSE.equals(taskTypeEnum.getBackendDevelopment())) {
                throw new ServiceException(msg + ": 任务状态异常, 请刷新后重试");
            }
            command.getBackendDevelopmentList().sort(Comparator.comparing(TaskDatTaskDetailCommand::getSort));
            int index = 1;
            for (TaskDatTaskDetailCommand detailCommand : command.getBackendDevelopmentList()) {
                if (detailCommand.getSort() == null || detailCommand.getSort() != index) {
                    throw new ServiceException(msg + ": 后端开发明细排序异常");
                }
                index++;
                if (detailCommand.getId() != null) {
                    detailIds.add(detailCommand.getId());
                }
            }
        }
        if (CollectionUtil.isNotEmpty(detailIds)) {
            int count = detailRepository.countByIds(detailIds);
            if (count != detailIds.size()) {
                throw new ServiceException(msg + ": 数据不存在, 请刷新后重试");
            }
        }
    }

}
